package myJs.tool

import scala.scalajs.js.Dynamic.{global => g}
import myJs.myPkg._
import myJs.myPkg.jquery.{$, JQuery}
import scalatags.Text.all._

import scala.scalajs.js
import myJs.Implicits._
import org.scalajs.dom.{Element, PerformanceNavigation, document, window}
import org.scalajs.dom.ext.Ajax
import shared._

import scala.collection.immutable.SeqMap
import scala.concurrent.ExecutionContext.Implicits.global
import scala.scalajs.js.{Date, JSON, UndefOr}
import myJs.tool.Tool._

import scala.concurrent.Future
import myJs.Implicits._

/** Created by yz on 20/7/2020
  */
trait ProjectTool {

  def dateInit = {
    val options = DatepickerOptions(format = Tool.pattern, autoclose = true, forceParse = true, language = "zh-CN")
    $(".myDatepicker").datepicker(options)
  }

  def getCurTabId = {
    $(".myMainUl li.active a").attr("href").get.replaceAll("^#", "")
  }

  def getCurTabId(parentJq: JQuery) = {
    parentJq.find(".myMainUl li.active a").attr("href").get.replaceAll("^#", "")
  }

  def getValues(inY: Element) = {
    if ($(inY).hasClass("select2MultiInput")) {
      if ($(inY).data("select2").isDefined) {
        $(inY).select2Val
      } else js.Array[String]()
    } else {
      $(inY).myVal.toMyArray
    }
  }

  def getTabJq(y: Element) = {
    $(y).parents(".tab-pane")
  }

  def saveDraft(pageId: String, y: Element) = {
    val inputJq = $(y).parents(".form-group").find(":input")
    val name = getTabJq(y).dataValue
    val data = inputJq.myVal
    window.localStorage.setItem(s"${pageId}_${name}", data)
  }

  def loadDraft(pageId: String, y: Element) = {
    val inputJq = $(y).parents(".form-group").find(":input")
    val name = getTabJq(y).dataValue
    val data = window.localStorage.getItem(s"${pageId}_${name}")
    inputJq.`val`(data)
  }

  def filterContentShow(y: Element) = {
    $(".filterContent").hide()
    val fieldName = Tool.getFilterDataFieldName(y)
    val contentJq = Tool.getTabJq(y).find(s"#${fieldName}Content")
    val contentPaddingTop = $(".page-content").css("padding-top").replaceAll("px$", "").toInt
    val yTop =
      $(y).offset().top - $(".page-header").height() - $("#tag").height() - contentPaddingTop + $(y).height() + 3
    val pageWidth = document.body.clientWidth
    val leftWidth = $(".page-sidebar-wrapper").width()
    val yTotalLeft = $(y).offset().left
    val yLeft = yTotalLeft - leftWidth
    val width = 210
    val trueYLeft = if (yTotalLeft + width > pageWidth) pageWidth - leftWidth - 220 - 6 else yLeft - 4
    contentJq.css("position", "absolute").css("top", yTop.toInt).css("left", trueYLeft.toInt).width(width)
    contentJq.show()
    Tool.filterContentFillBeforeValue(contentJq)
  }

  def filterContentShowFront(y: Element) = {
    $(s".filterContent").hide()
    val fieldName = Tool.getFilterDataFieldName(y)
    val contentJq = $(s"[id='${fieldName}Content']")
    val yTop = $(y).offset().top - $(".page-header").height() - $(".headerRow").height() + $(y).height() + 3 - 10
    val pageWidth = document.body.clientWidth
    val yTotalLeft = $(y).offset().left
    val leftWidth = $(".container").css("margin-left").px2Double -
      15
    val yLeft = yTotalLeft - leftWidth
    val width = 210
    val trueYLeft = if (yTotalLeft + width > pageWidth) pageWidth - leftWidth - 220 - 6 else yLeft
    contentJq.css("top", yTop.toInt).css("left", trueYLeft.toInt).width(width)
    contentJq.show()
    Tool.filterContentFillBeforeValue(contentJq)
  }

  def filterContentShowNoTab(y: Element) = {
    $(".filterContent").hide()
    val fieldName = Tool.getFilterDataFieldName(y)
    val contentJq = $(s"#${fieldName}Content")
    val contentPaddingTop = $(".page-content").css("padding-top").replaceAll("px$", "").toInt
    val yTop =
      $(y).offset().top - $(".page-header").height() - $("#tag").height() - contentPaddingTop + $(y).height() + 3
    val pageWidth = document.body.clientWidth
    val leftWidth = $(".page-sidebar-wrapper").width()
    val yTotalLeft = $(y).offset().left
    val yLeft = yTotalLeft - leftWidth
    val width = 210
    val trueYLeft = if (yTotalLeft + width > pageWidth) pageWidth - leftWidth - 220 - 6 else yLeft - 4
    contentJq.css("position", "absolute").css("top", yTop.toInt).css("left", trueYLeft.toInt).width(width)
    contentJq.show()
    Tool.filterContentFillBeforeValue(contentJq)
  }

  def execFilter(sortData: JArJDJAn, queryMap: Map[String, js.Any], getColumnV: (String, js.Any) => String) = {

    val searchDicts = queryMap("search").toJArJDJAn.toList

    def loop(acc: JArJDJAn, searchs: List[JDJAn]): JArJDJAn = {
      searchs match {
        case Nil => acc
        case y :: ys =>
          val name = y.myGet("name")
          val curFilterData = y.myGet("kind") match {
            case "date" =>
              val startTime = y("startTime")
              val endTime = y("endTime")
              acc.filter { row =>
                val dbDate = row(name)
                val startB = if (startTime.toString.nonBlank) {
                  Tool.timeBefore(startTime.toString, dbDate.toString)
                } else true
                val endB = if (endTime.toString.nonBlank) {
                  Tool.timeAfter(endTime.toString, dbDate.toString)
                } else true
                startB && endB
              }
            case "checkbox" =>
              val vs = y("value").toJArS
              acc.filter { row =>
                val fV = getColumnV(name, row(name))
                vs.exists(fV == _)
              }
            case "num" =>
              val minV = y.myGet("min")
              val maxV = y.myGet("max")
              acc.filter { row =>
                val v = getColumnV(name, row(name))
                v.isDouble && {
                  val dbDouble = v.toDouble
                  val minB = if (minV.isDouble) {
                    dbDouble >= minV.toDouble
                  } else true
                  val maxB = if (maxV.isDouble) {
                    dbDouble <= maxV.toDouble
                  } else true
                  minB && maxB
                }
              }
            case "text" =>
              val vs = y.myGet("value").split(";")
              val searchType = y.myGet("searchType")
              acc.filter { row =>
                val fV = getColumnV(name, row(name))
                searchType match {
                  case "equals" =>
                    vs.exists(v => fV == v)
                  case "like" =>
                    vs.exists(v => fV.contains(v))
                }
              }
          }
          loop(curFilterData, ys)
      }
    }

    loop(sortData, searchDicts)
  }

  def sortExec(data: JArJDJAn, queryMap: Map[String, js.Any], getColumnV: (String, js.Any) => String) = {
    val sortOp = queryMap.get("sort").map(_.toJDS)
    val sortData = sortOp
      .map { dict =>
        val sort = dict("field")
        val (ascSortData, blankDatas) = dict("kind") match {
          case "int" =>
            val blankDatas = data.filter(_(sort).toString.trim.isEmpty)
            val notBlankDatas = data.filterNot(_(sort).toString.trim.isEmpty).sortBy { x =>
              getColumnV(sort, x(sort)).toDouble
            }
            (notBlankDatas, blankDatas)
          case "str" =>
            val sortData = data.sortBy(_(sort).toString)
            (sortData, js.Array())
        }
        dict("order") match {
          case "desc" => ascSortData.reverse ++ blankDatas
          case "asc" => ascSortData
        }
      }
      .getOrElse(data)
    sortData
  }

  def getMissionId = {
    g.missionId.toString
  }

  val dataMap= SeqMap(
    "id" -> "ID",
    "snpNumber" -> "rs",
    "gene" -> "Gene",
    "nutrient" -> "Related nutrients",
    "or" -> "OR",
    "p" -> "P value",
    "articleTitle" -> "Article title",
    "articleDoi" -> "Articel DOI"
  )

  val annoMap= SeqMap(
    "rsNumber" -> "rs",
    "position" -> "Position",
    "alleles" -> "Alleles",
    "variationType" -> "Variation Type",
    "frequency" -> "Frequency Number",
    "clinicalSignificance" -> "Clinical Significance",
    "geneConsequence" -> "Gene : Consequence",
    "publications" -> "Publications Number"
  )

  val geneMap=SeqMap("entry" -> "Entry", "symbol" -> "Symbol", "name" -> "Name", "pathway" -> "PATHWAY")

  def getId = {
    g.id.toString
  }

  def getRsNumber = {
    g.rsNumber.toString
  }

  def getSymbol = {
    g.symbol.toString
  }

}
